﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using System.Reflection;
using WebAPI中实现属性注入.Attributes;

namespace WebAPI中实现属性注入.Extensions
{
    public static class PropertyInjectionExtensions
    {
        /// <summary>
        /// 注册属性注入支持
        /// </summary>
        public static IServiceCollection AddPropertyInjection(this IServiceCollection services)
        {
            // 替换默认的控制器激活器
            services.AddSingleton<IControllerActivator, PropertyInjectionControllerActivator>();
            return services;
        }
    }

    /// <summary>
    /// 支持属性注入的控制器激活器
    /// </summary>
    public class PropertyInjectionControllerActivator : IControllerActivator
    {
        public object Create(ControllerContext context)
        {
            // 获取控制器类型
            var controllerType = context.ActionDescriptor.ControllerTypeInfo.AsType();

            // 创建控制器实例（使用无参构造函数）
            var controller = Activator.CreateInstance(controllerType);

            // 执行属性注入
            InjectProperties(context.HttpContext.RequestServices, controller);

            return controller;
        }

        public void Release(ControllerContext context, object controller)
        {
            // 如果控制器实现了IDisposable，释放资源
            if (controller is IDisposable disposable)
            {
                disposable.Dispose();
            }
        }

        /// <summary>
        /// 为对象的属性注入依赖
        /// </summary>
        private void InjectProperties(IServiceProvider serviceProvider, object target)
        {
            if (target == null)
                return;

            // 获取所有标记了[Inject]特性的公共属性
            var properties = target.GetType()
                .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                .Where(p => p.IsDefined(typeof(InjectAttribute), inherit: true))
                .Where(p => p.CanWrite);

            foreach (var property in properties)
            {
                // 从服务容器中获取属性对应的服务
                var service = serviceProvider.GetService(property.PropertyType);
                if (service != null)
                {
                    // 注入服务到属性
                    property.SetValue(target, service);
                }
            }
        }
    }
}
